From 309df7ec5e65782cf062fb1c5ae97939d1614882 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 25 Aug 2020 12:26:19 +0100 Subject: [PATCH] add CR read to DMI interface --- src/soc/debug/dmi.py | 2 +- src/soc/regfile/regfiles.py | 3 ++- src/soc/regfile/virtual_port.py | 31 ++++++++++++++++++++---------- src/soc/simple/issuer.py | 15 +++++++++++++-- src/soc/simple/test/test_issuer.py | 4 ++++ 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/soc/debug/dmi.py b/src/soc/debug/dmi.py index 9c28d2b9..71e49359 100644 --- a/src/soc/debug/dmi.py +++ b/src/soc/debug/dmi.py @@ -139,7 +139,7 @@ class CoreDebug(Elaboratable): LOG_INDEX_BITS = log2_int(self.LOG_LENGTH) # Single cycle register accesses on DMI except for GSPR data - with m.Switch(.dmi.addr_i): + with m.Switch(dmi.addr_i): with m.Case(DBGCore.GSPR_DATA): comb += dmi.ack_o.eq(dbg_gpr.ack) comb += dbg_gpr.req.eq(dmi.req_i) diff --git a/src/soc/regfile/regfiles.py b/src/soc/regfile/regfiles.py index 58211449..505fb587 100644 --- a/src/soc/regfile/regfiles.py +++ b/src/soc/regfile/regfiles.py @@ -110,11 +110,12 @@ class CRRegs(VirtualRegPort): * write-through capability (read on same cycle as write) """ def __init__(self): - super().__init__(32, 8) + super().__init__(32, 8, rd2=True) self.w_ports = {'full_cr': self.full_wr, # 32-bit (masked, 8-en lines) 'cr_a': self.write_port("dest1"), # 4-bit, unary-indexed 'cr_b': self.write_port("dest2")} # 4-bit, unary-indexed self.r_ports = {'full_cr': self.full_rd, # 32-bit (masked, 8-en lines) + 'full_cr_dbg': self.full_rd2, # for DMI 'cr_a': self.read_port("src1"), 'cr_b': self.read_port("src2"), 'cr_c': self.read_port("src3")} diff --git a/src/soc/regfile/virtual_port.py b/src/soc/regfile/virtual_port.py index ec1ee2c3..f4393e15 100644 --- a/src/soc/regfile/virtual_port.py +++ b/src/soc/regfile/virtual_port.py @@ -18,9 +18,10 @@ from soc.regfile.regfile import RegFileArray class VirtualRegPort(RegFileArray): - def __init__(self, bitwidth, n_regs): + def __init__(self, bitwidth, n_regs, rd2=False): self.bitwidth = bitwidth self.nregs = n_regs + self.rd2 = rd2 # eurgh hack self.regwidth = regwidth = bitwidth // n_regs super().__init__(self.regwidth, n_regs) @@ -31,17 +32,15 @@ class VirtualRegPort(RegFileArray): self.full_rd = RecordObject([("ren", n_regs), ("data_o", bitwidth)], # *full* wid name="full_rd") + if not rd2: + return + self.full_rd2 = RecordObject([("ren", n_regs), + ("data_o", bitwidth)], # *full* wid + name="full_rd2") - def elaborate(self, platform): - m = super().elaborate(platform) + def connect_full_rd(self, m, rfull, name): comb = m.d.comb - - # for internal use only. - wr_regs = self.write_reg_port(f"w") - rd_regs = self.read_reg_port(f"r") - - # connect up full read port - rfull = self.full_rd + rd_regs = self.read_reg_port(name) # wire up the enable signals and chain-accumulate the data l = map(lambda port: port.data_o, rd_regs) # get port data(s) @@ -50,6 +49,18 @@ class VirtualRegPort(RegFileArray): comb += rfull.data_o.eq(Cat(*l)) # we like Cat on lists comb += Cat(*le).eq(rfull.ren) + def elaborate(self, platform): + m = super().elaborate(platform) + comb = m.d.comb + + # for internal use only. + wr_regs = self.write_reg_port(f"w") + + # connect up full read port + self.connect_full_rd(m, self.full_rd, "r") + if self.rd2: # hack! + self.connect_full_rd(m, self.full_rd2, "r2") + # connect up full write port wfull = self.full_wr diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index cf516099..1c92512a 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -73,7 +73,9 @@ class TestIssuer(Elaboratable): # DMI interface access intrf = self.core.regs.rf['int'] + crrf = self.core.regs.rf['cr'] self.int_r = intrf.r_ports['dmi'] # INT read + self.cr_r = crrf.r_ports['full_cr_dbg'] # CR read # hack method of keeping an eye on whether branch/trap set the PC self.state_nia = self.core.regs.rf['state'].w_ports['nia'] @@ -92,8 +94,7 @@ class TestIssuer(Elaboratable): m.submodules.dec2 = pdecode2 = self.pdecode2 # convenience - dmi = dbg.dmi - d_reg = dbg.dbg_gpr + dmi, d_reg, d_cr = dbg.dmi, dbg.dbg_gpr, dbg.dbg_cr intrf = self.core.regs.rf['int'] # clock delay power-on reset @@ -262,6 +263,16 @@ class TestIssuer(Elaboratable): comb += d_reg.data.eq(self.int_r.data_o) comb += d_reg.ack.eq(1) + # sigh same thing for CR debug + with m.If(d_cr.req): # request for regfile access being made + comb += self.cr_r.ren.eq(0b11111111) # enable all + d_cr_delay = Signal() + sync += d_cr_delay.eq(d_cr.req) + with m.If(d_cr_delay): + # data arrives one clock later + comb += d_cr.data.eq(self.cr_r.data_o) + comb += d_cr.ack.eq(1) + return m def __iter__(self): diff --git a/src/soc/simple/test/test_issuer.py b/src/soc/simple/test/test_issuer.py index 17578632..f83c17b5 100644 --- a/src/soc/simple/test/test_issuer.py +++ b/src/soc/simple/test/test_issuer.py @@ -277,6 +277,10 @@ class TestRunner(FHDLTestCase): yield yield + # get CR + cr = yield from get_dmi(dmi, DBGCore.CR) + print ("after test %s cr value %x" % (test.name, cr)) + # test of dmi reg get for int_reg in range(32): yield from set_dmi(dmi, DBGCore.GSPR_IDX, int_reg) -- 2.30.2