Compare commits
4 Commits
9e53a6ba43
...
12ddbeb508
Author | SHA1 | Date |
---|---|---|
David Anderson | 12ddbeb508 | |
David Anderson | eb2bb40fd3 | |
David Anderson | 76a1a36006 | |
David Anderson | f45ff0d105 |
|
@ -0,0 +1,190 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
lip "github.com/charmbracelet/lipgloss"
|
||||
"github.com/creachadair/mds/slice"
|
||||
)
|
||||
|
||||
type HexViewUpdateMem struct {
|
||||
addr int
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
type HexView struct {
|
||||
AddrStyle lip.Style
|
||||
ZeroStyle lip.Style
|
||||
HexStyle lip.Style
|
||||
|
||||
write func(int, byte) tea.Cmd
|
||||
firstAddr int // top of viewport
|
||||
bytes []byte
|
||||
selectedAddr int
|
||||
editing bool
|
||||
editNibble int // 0 or 1
|
||||
newByte byte
|
||||
}
|
||||
|
||||
func NewHexView(size int, writeByte func(addr int, val byte) tea.Cmd) HexView {
|
||||
st := lip.NewStyle()
|
||||
ret := HexView{
|
||||
AddrStyle: st,
|
||||
ZeroStyle: st,
|
||||
HexStyle: st,
|
||||
write: writeByte,
|
||||
bytes: make([]byte, size),
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m HexView) Width() int {
|
||||
hexdumpWidth := 16*3 + 2 // including spaces between dquads
|
||||
addrWidth := m.addrNibbles() // Hex nibbles needed to represent all addrs
|
||||
return addrWidth + 4 + hexdumpWidth
|
||||
}
|
||||
|
||||
func (m HexView) SelectedAddr() int {
|
||||
return m.selectedAddr
|
||||
}
|
||||
|
||||
func (m HexView) addrFormat() string {
|
||||
return fmt.Sprintf("%%%dx", m.addrNibbles())
|
||||
}
|
||||
|
||||
func (m HexView) addrNibbles() int {
|
||||
return int(math.Ceil(math.Log2(float64(len(m.bytes)-1)))) / 4
|
||||
}
|
||||
|
||||
func (m HexView) Update(msg tea.Msg) (HexView, tea.Cmd) {
|
||||
if m.editing {
|
||||
return m.updateEditMode(msg)
|
||||
} else {
|
||||
return m.updateViewMode(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (m HexView) updateEditMode(msg tea.Msg) (HexView, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case HexViewUpdateMem:
|
||||
copy(m.bytes[msg.addr:], msg.bytes)
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyLeft:
|
||||
if m.editNibble == 1 {
|
||||
m.editNibble = 0
|
||||
}
|
||||
case tea.KeyRight:
|
||||
if m.editNibble == 0 {
|
||||
m.editNibble = 1
|
||||
}
|
||||
case tea.KeyEsc:
|
||||
m.editing = false
|
||||
case tea.KeyEnter:
|
||||
m.editing = false
|
||||
return m, m.write(m.selectedAddr, m.newByte)
|
||||
case tea.KeyRunes:
|
||||
if unicode.In(msg.Runes[0], unicode.ASCII_Hex_Digit) {
|
||||
nibble := hexToNibble(msg.Runes[0])
|
||||
if m.editNibble == 0 {
|
||||
m.newByte = (nibble << 4) + (m.newByte & 0xF)
|
||||
m.editNibble++
|
||||
} else {
|
||||
m.newByte = (m.newByte & 0xF0) + nibble
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func hexToNibble(r rune) byte {
|
||||
switch {
|
||||
case r >= '0' && r <= '9':
|
||||
return byte(r - '0')
|
||||
case r >= 'a' && r <= 'f':
|
||||
return byte(r - 'a' + 10)
|
||||
case r >= 'A' && r <= 'F':
|
||||
return byte(r - 'A' + 10)
|
||||
}
|
||||
panic("invalid hex rune")
|
||||
}
|
||||
|
||||
func (m HexView) updateViewMode(msg tea.Msg) (HexView, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case HexViewUpdateMem:
|
||||
copy(m.bytes[msg.addr:], msg.bytes)
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "up":
|
||||
if m.selectedAddr >= 16 {
|
||||
m.selectedAddr -= 16
|
||||
}
|
||||
case "down":
|
||||
if m.selectedAddr < len(m.bytes)-16 {
|
||||
m.selectedAddr += 16
|
||||
}
|
||||
case "left":
|
||||
if m.selectedAddr > 0 {
|
||||
m.selectedAddr--
|
||||
}
|
||||
case "right":
|
||||
if m.selectedAddr < len(m.bytes)-1 {
|
||||
m.selectedAddr++
|
||||
}
|
||||
case "pgdown":
|
||||
// TODO
|
||||
case "pgup":
|
||||
// TODO
|
||||
case "w":
|
||||
m.editing = true
|
||||
m.editNibble = 0
|
||||
m.newByte = m.bytes[m.selectedAddr]
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m HexView) View(height int) string {
|
||||
maxLen := 16 * height
|
||||
endAddr := min(len(m.bytes), m.firstAddr+maxLen)
|
||||
var ret strings.Builder
|
||||
addrFormat := m.addrFormat()
|
||||
for line, bytes := range slice.Chunks(m.bytes[m.firstAddr:endAddr], 16) {
|
||||
lineAddr := m.firstAddr + (16 * line)
|
||||
ret.WriteString(m.AddrStyle.Render(fmt.Sprintf(addrFormat, lineAddr)))
|
||||
ret.WriteString(" ")
|
||||
for i, b := range bytes {
|
||||
byteAddr := lineAddr + i
|
||||
if i == 8 {
|
||||
ret.WriteString(" ")
|
||||
} else if i != 0 {
|
||||
ret.WriteByte(' ')
|
||||
}
|
||||
if m.editing && byteAddr == m.selectedAddr {
|
||||
st := m.HexStyle.Underline(true)
|
||||
s1, s2 := st.Reverse(true), st
|
||||
if m.editNibble == 1 {
|
||||
s1, s2 = s2, s1
|
||||
}
|
||||
b = m.newByte
|
||||
ret.WriteString(s1.Render(fmt.Sprintf("%01x", b>>4)))
|
||||
ret.WriteString(s2.Render(fmt.Sprintf("%01x", b&0xF)))
|
||||
} else {
|
||||
st := m.HexStyle
|
||||
if m.selectedAddr == byteAddr {
|
||||
st = m.HexStyle.Reverse(true)
|
||||
} else if b == 0 {
|
||||
st = m.ZeroStyle
|
||||
}
|
||||
ret.WriteString(st.Render(fmt.Sprintf("%02x", b)))
|
||||
}
|
||||
}
|
||||
ret.WriteByte('\n')
|
||||
}
|
||||
return strings.TrimRight(ret.String(), "\n")
|
||||
}
|
|
@ -19,15 +19,13 @@ func main() {
|
|||
}
|
||||
defer dbg.Close()
|
||||
|
||||
fmt.Println("Writing...")
|
||||
if err := dbg.Write(0x42, 123); err != nil {
|
||||
log.Fatalf("writing to memory: %v", err)
|
||||
}
|
||||
v, err := dbg.Read(0x42)
|
||||
if err != nil {
|
||||
log.Fatalf("reading from memory: %v", err)
|
||||
|
||||
if err := UI(dbg); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("addr 0: %02x\n", v)
|
||||
}
|
||||
|
||||
type Debugger struct {
|
||||
|
@ -73,7 +71,7 @@ func (d *Debugger) Read(addr int) (byte, error) {
|
|||
}
|
||||
|
||||
packet := encode(addr, false, 0)
|
||||
fmt.Printf("Writing: %02x %02x %02x %02x\n", packet[0], packet[1], packet[2], packet[3])
|
||||
//fmt.Printf("Writing: %02x %02x %02x %02x\n", packet[0], packet[1], packet[2], packet[3])
|
||||
if _, err := d.port.Write(packet[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -97,9 +95,21 @@ func (d *Debugger) Write(addr int, val byte) error {
|
|||
}
|
||||
|
||||
packet := encode(addr, true, val)
|
||||
fmt.Printf("Writing: %02x %02x %02x %02x\n", packet[0], packet[1], packet[2], packet[3])
|
||||
//fmt.Printf("Writing: %02x %02x %02x %02x\n", packet[0], packet[1], packet[2], packet[3])
|
||||
if _, err := d.port.Write(packet[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Debugger) Dump(startAddr int, count int) ([]byte, error) {
|
||||
ret := make([]byte, count)
|
||||
var err error
|
||||
for i := range ret {
|
||||
ret[i], err = d.Read(startAddr + i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
lip "github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func UI(dbg *Debugger) error {
|
||||
p := tea.NewProgram(initialModel(dbg)) //failed{0, 0, true}, tea.WithAltScreen())
|
||||
if _, err := p.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
amber = lip.Color("#ffb00")
|
||||
slate = lip.Color("235")
|
||||
text = lip.NewStyle().Foreground(amber).Background(slate)
|
||||
faintText = text.Faint(true)
|
||||
box = text.Border(lip.NormalBorder(), true, true, true, true).
|
||||
BorderForeground(amber).
|
||||
BorderBackground(slate)
|
||||
)
|
||||
|
||||
type msgErr struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type msgUpdateStatus struct {
|
||||
status string
|
||||
}
|
||||
|
||||
type debugger struct {
|
||||
width int
|
||||
height int
|
||||
dbg *Debugger
|
||||
hex HexView
|
||||
lastErr error
|
||||
bottomMsg string
|
||||
}
|
||||
|
||||
func initialModel(dbg *Debugger) debugger {
|
||||
ret := debugger{
|
||||
width: 0,
|
||||
height: 0,
|
||||
dbg: dbg,
|
||||
bottomMsg: "",
|
||||
}
|
||||
hex := NewHexView(128*1024, ret.writeByte)
|
||||
hex.AddrStyle = text
|
||||
hex.ZeroStyle = faintText
|
||||
hex.HexStyle = text
|
||||
ret.hex = hex
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m debugger) Init() tea.Cmd {
|
||||
return m.dumpMemory(0x200)
|
||||
}
|
||||
|
||||
func staticMsg(msg tea.Msg) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
func (m debugger) dumpMemory(count int) tea.Cmd {
|
||||
var ret []tea.Cmd
|
||||
for i := 0; i < count; i += 16 {
|
||||
ret = append(ret, func() tea.Msg {
|
||||
mem, err := m.dbg.Dump(i, 16)
|
||||
if err != nil {
|
||||
return msgErr{err}
|
||||
}
|
||||
return HexViewUpdateMem{i, mem}
|
||||
})
|
||||
}
|
||||
return tea.Sequence(ret...)
|
||||
}
|
||||
|
||||
func (m debugger) writeByte(addr int, val byte) tea.Cmd {
|
||||
return tea.Sequence(
|
||||
staticMsg(msgUpdateStatus{"Writing..."}),
|
||||
func() tea.Msg {
|
||||
if err := m.dbg.Write(addr, val); err != nil {
|
||||
return msgUpdateStatus{fmt.Sprintf("Write failed: %v", err)}
|
||||
}
|
||||
return tea.BatchMsg{
|
||||
staticMsg(HexViewUpdateMem{addr, []byte{val}}),
|
||||
staticMsg(msgUpdateStatus{"Written!"}),
|
||||
}
|
||||
},
|
||||
m.dumpMemory(0x200),
|
||||
)
|
||||
}
|
||||
|
||||
func (m debugger) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c", "q":
|
||||
return m, tea.Quit
|
||||
case "r":
|
||||
return m, m.dumpMemory(0x200)
|
||||
}
|
||||
case msgErr:
|
||||
m.lastErr = msg.err
|
||||
return m, nil
|
||||
case msgUpdateStatus:
|
||||
m.bottomMsg = msg.status
|
||||
}
|
||||
var cmd tea.Cmd
|
||||
m.hex, cmd = m.hex.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
// func (m debugger) values(addr int) string {
|
||||
// var v [4]byte
|
||||
// copy(v[:], m.vram[addr:])
|
||||
// var out strings.Builder
|
||||
// out.WriteString(text.Render("Bin: "))
|
||||
// out.WriteString(renderBytes(v[:], "%08b", "_"))
|
||||
// out.WriteByte('\n')
|
||||
// out.WriteString(text.Render("Hex: "))
|
||||
// out.WriteString(renderBytes(v[:], "%02x", "_"))
|
||||
// out.WriteByte('\n')
|
||||
// out.WriteString(text.Render("Dec: "))
|
||||
// out.WriteString(faintText.Render("["))
|
||||
// out.WriteString(dimZero(fmt.Sprintf("%3d", v[0])))
|
||||
// out.WriteString(faintText.Render("] ["))
|
||||
// out.WriteString(dimZero(fmt.Sprintf("%5d", binary.BigEndian.Uint16(v[:]))))
|
||||
// out.WriteString(faintText.Render("] ["))
|
||||
// out.WriteString(dimZero(fmt.Sprintf("%10d", binary.BigEndian.Uint32(v[:]))))
|
||||
// out.WriteString(faintText.Render("]"))
|
||||
|
||||
// return out.String()
|
||||
// }
|
||||
|
||||
func (m debugger) View() string {
|
||||
if m.width < 80 || m.height < 20 {
|
||||
return lip.Place(m.width, m.height, lip.Center, lip.Center, "Please embiggen your terminal")
|
||||
}
|
||||
|
||||
statusBar := text.Width(m.width).Height(1).Align(lip.Center)
|
||||
topSegment := statusBar.Width(m.width / 3).Reverse(true)
|
||||
|
||||
hexBox := lip.NewStyle().Border(lip.NormalBorder()).BorderForeground(amber).BorderBackground(slate).Padding(1, 2)
|
||||
hexHeight := m.height - 2 - hexBox.GetVerticalFrameSize()
|
||||
hex := hexBox.Render(m.hex.View(hexHeight))
|
||||
|
||||
topLeft := text.Reverse(true).Bold(true).Render("Addr: ") + text.Reverse(true).Render(fmt.Sprintf("0x%-5x", m.hex.SelectedAddr()))
|
||||
topLeft = topSegment.Padding(0, 1).Align(lip.Left).Render(topLeft)
|
||||
topMid := topSegment.Bold(true).Render("GARY Debugger")
|
||||
topRight := topSegment.Render("")
|
||||
topStatus := lip.JoinHorizontal(lip.Top, topLeft, topMid, topRight)
|
||||
bottomStatus := statusBar.Render(m.bottomMsg)
|
||||
|
||||
top := lip.JoinVertical(lip.Center, topStatus, hex, bottomStatus)
|
||||
return top
|
||||
}
|
||||
|
||||
func renderByte(b byte, format string) string {
|
||||
ret := fmt.Sprintf(format, b)
|
||||
if b == 0 {
|
||||
return faintText.Render(ret)
|
||||
}
|
||||
return text.Render(ret)
|
||||
}
|
||||
|
||||
func renderBytes(bs []byte, format string, sep string) string {
|
||||
var s strings.Builder
|
||||
for i, b := range bs {
|
||||
s.WriteString(renderByte(b, format))
|
||||
if i < len(bs)-1 {
|
||||
s.WriteString(faintText.Render(sep))
|
||||
}
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func dimZero(s string) string {
|
||||
allZero := true
|
||||
for _, r := range s {
|
||||
if !unicode.IsSpace(r) && r != '0' {
|
||||
allZero = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allZero {
|
||||
return faintText.Render(s)
|
||||
}
|
||||
return text.Render(s)
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
dfu-util
|
||||
fujprog
|
||||
git
|
||||
go_1_22
|
||||
go_1_23
|
||||
gotools
|
||||
gtkwave
|
||||
imagemagick
|
||||
|
|
32
go.mod
32
go.mod
|
@ -1,9 +1,33 @@
|
|||
module git.sentinel65x.com/dave/gary
|
||||
|
||||
go 1.22.6
|
||||
go 1.23
|
||||
|
||||
toolchain go1.23.0
|
||||
|
||||
require (
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
go.bug.st/serial v1.6.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.1.1
|
||||
github.com/charmbracelet/lipgloss v0.13.0
|
||||
github.com/creachadair/mds v0.21.2
|
||||
go.bug.st/serial v1.6.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
)
|
||||
|
|
45
go.sum
45
go.sum
|
@ -1,6 +1,51 @@
|
|||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY=
|
||||
github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
|
||||
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
|
||||
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
||||
github.com/creachadair/mds v0.21.2 h1:D5130qi/kqmu+gGUQyDNOhrocGQp075ziTCgttxhh3k=
|
||||
github.com/creachadair/mds v0.21.2/go.mod h1:1ltMWZd9yXhaHEoZwBialMaviWVUpRPvMwVP7saFAzM=
|
||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8=
|
||||
go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
|
|
|
@ -457,7 +457,10 @@ module mkEBRCore#(EBRPortConfig cfgA,
|
|||
if (!rcfgA.enabled)
|
||||
noAction;
|
||||
else
|
||||
vEBR.portA.put(chip_select, write, zeroExtend(pack(address)), zeroExtend(pack(datain)));
|
||||
vEBR.portA.put(chip_select,
|
||||
write,
|
||||
zeroExtend(pack(address)) << valueOf(addr_a_pad),
|
||||
zeroExtend(pack(datain)));
|
||||
endmethod
|
||||
method data_a read();
|
||||
if (!rcfgA.enabled)
|
||||
|
@ -472,7 +475,10 @@ module mkEBRCore#(EBRPortConfig cfgA,
|
|||
if (!rcfgB.enabled)
|
||||
noAction;
|
||||
else
|
||||
vEBR.portB.put(chip_select, write, zeroExtend(pack(address)), zeroExtend(pack(datain)));
|
||||
vEBR.portB.put(chip_select,
|
||||
write,
|
||||
zeroExtend(pack(address)) << valueOf(addr_b_pad),
|
||||
zeroExtend(pack(datain)));
|
||||
endmethod
|
||||
method data_b read();
|
||||
if (!rcfgB.enabled)
|
||||
|
|
|
@ -105,6 +105,7 @@ module mkTestFull(FSM);
|
|||
|
||||
let fsm <- mkFSM(seq
|
||||
dut.cpu.request.put(VRAMRequest{addr: 1, data: tagged Valid 42});
|
||||
dut.cpu.request.put(VRAMRequest{addr: 2, data: tagged Valid 45});
|
||||
dut.cpu.request.put(VRAMRequest{addr: 1, data: tagged Invalid});
|
||||
action
|
||||
let resp <- dut.cpu.response.get();
|
||||
|
@ -112,6 +113,13 @@ module mkTestFull(FSM);
|
|||
$display("vram read: ", fshow(resp));
|
||||
dynamicAssert(resp.data == 42, "wrong data read after writing");
|
||||
endaction
|
||||
dut.cpu.request.put(VRAMRequest{addr: 2, data: tagged Invalid});
|
||||
action
|
||||
let resp <- dut.cpu.response.get();
|
||||
if (testflags.verbose)
|
||||
$display("vram read: ", fshow(resp));
|
||||
dynamicAssert(resp.data == 45, "wrong data read after writing");
|
||||
endaction
|
||||
endseq);
|
||||
return fsm;
|
||||
endmodule
|
||||
|
|
Loading…
Reference in New Issue