def __init__(self, x_len: int): super().__init__(x_len) io = self.io sum_ = io.A + m.mux([io.B, -io.B], io.op[0]) cmp = m.uint(m.mux([m.mux([io.A[-1], io.B[-1]], io.op[1]), sum_[-1]], io.A[-1] == io.B[-1]), x_len) shin = m.mux([io.A[::-1], io.A], io.op[3]) shiftr = m.uint(m.sint( m.concat(shin, io.op[0] & shin[x_len - 1]) ) >> m.sint(m.zext(io.B, 1)))[:x_len] shiftl = shiftr[::-1] @m.inline_combinational() def alu(): if (io.op == ALUOP.ADD) | (io.op == ALUOP.SUB): io.O @= sum_ elif (io.op == ALUOP.SLT) | (io.op == ALUOP.SLTU): io.O @= cmp elif (io.op == ALUOP.SRA) | (io.op == ALUOP.SRL): io.O @= shiftr elif io.op == ALUOP.SLL: io.O @= shiftl elif io.op == ALUOP.AND: io.O @= io.A & io.B elif io.op == ALUOP.OR: io.O @= io.A | io.B elif io.op == ALUOP.XOR: io.O @= io.A ^ io.B elif io.op == ALUOP.COPY_A: io.O @= io.A else: io.O @= io.B io.sum_ @= sum_
def alu(): if io.op == ALUOP.ADD: io.O @= io.A + io.B elif io.op == ALUOP.SUB: io.O @= io.A - io.B elif io.op == ALUOP.SRA: io.O @= m.uint(m.sint(io.A) >> m.sint(io.B)) elif io.op == ALUOP.SRL: io.O @= io.A >> io.B elif io.op == ALUOP.SLL: io.O @= io.A << io.B elif io.op == ALUOP.SLT: io.O @= m.uint(m.sint(io.A) < m.sint(io.B), x_len) elif io.op == ALUOP.SLTU: io.O @= m.uint(io.A < io.B, x_len) elif io.op == ALUOP.AND: io.O @= io.A & io.B elif io.op == ALUOP.OR: io.O @= io.A | io.B elif io.op == ALUOP.XOR: io.O @= io.A ^ io.B elif io.op == ALUOP.COPY_A: io.O @= io.A else: io.O @= io.B io.sum_ @= io.A + m.mux([io.B, -io.B], io.op[0])
def __init__(self, x_len): super().__init__(x_len) inst = self.io.inst Iimm = m.sext_to(m.sint(inst[20:32]), x_len) Simm = m.sext_to(m.sint(m.concat(inst[7:12], inst[25:32])), x_len) Bimm = m.sext_to( m.sint( m.concat(m.bits(0, 1), inst[8:12], inst[25:31], inst[7], inst[31])), x_len) Uimm = m.concat(m.bits(0, 12), inst[12:32]) Jimm = m.sext_to( m.sint( m.concat(m.bits(0, 1), inst[21:25], inst[25:31], inst[20], inst[12:20], inst[31])), x_len) Zimm = m.sint(m.zext_to(inst[15:20], x_len)) self.io.O @= m.uint( m.dict_lookup( { IMM_I: Iimm, IMM_S: Simm, IMM_B: Bimm, IMM_U: Uimm, IMM_J: Jimm, IMM_Z: Zimm }, self.io.sel, Iimm & -2))
def test_sext(value): in_ = sint(value, 16) # TODO(rsetaluri): Ideally, zext(sint) should return an object of type # SintType, instead it returns an object of type ArrayType. For now, we wrap # the result of zext() in sint(). out = sint(sext(in_, 16)) assert len(out.bits()) == 32 assert int(out) == value
class BrCond_DUT(m.Circuit): _IGNORE_UNUSED_ = True io = m.IO( done=m.Out(m.Bit), out=m.Out(m.Bit), taken=m.Out(m.Bit) ) + m.ClockIO() br_cond = BrCond(x_len)() io.taken @= br_cond.taken control = Control(x_len)() br_cond.br_type @= control.br_type insts = [ B(Funct3.BEQ, 0, 0, 0), B(Funct3.BNE, 0, 0, 0), B(Funct3.BLT, 0, 0, 0), B(Funct3.BGE, 0, 0, 0), B(Funct3.BLTU, 0, 0, 0), B(Funct3.BGEU, 0, 0, 0), ] * 10 n = len(insts) counter = CounterModM(n, n.bit_length()) control.inst @= m.mux(insts, counter.O) io.done @= counter.COUT rs1 = [BV.random(x_len) for _ in range(n)] rs2 = [BV.random(x_len) for _ in range(n)] br_cond.rs1 @= m.mux(rs1, counter.O) br_cond.rs2 @= m.mux(rs2, counter.O) eq = [a == b for a, b in zip(rs1, rs2)] ne = [a != b for a, b in zip(rs1, rs2)] lt = [m.sint(a) < m.sint(b) for a, b in zip(rs1, rs2)] ge = [m.sint(a) >= m.sint(b) for a, b in zip(rs1, rs2)] ltu = [a < b for a, b in zip(rs1, rs2)] geu = [a >= b for a, b in zip(rs1, rs2)] @m.inline_combinational() def logic(): if control.br_type == BR_EQ: io.out @= m.mux(eq, counter.O) elif control.br_type == BR_NE: io.out @= m.mux(ne, counter.O) elif control.br_type == BR_LT: io.out @= m.mux(lt, counter.O) elif control.br_type == BR_GE: io.out @= m.mux(ge, counter.O) elif control.br_type == BR_LTU: io.out @= m.mux(ltu, counter.O) elif control.br_type == BR_GEU: io.out @= m.mux(geu, counter.O) else: io.out @= False
def test_array(): assert isinstance(array(1, 4), ArrayType) assert isinstance(array([1, 0, 0, 0]), ArrayType) assert isinstance(array(VCC), ArrayType) assert isinstance(array(array(1, 4)), ArrayType) assert isinstance(array(uint(1, 4)), ArrayType) assert isinstance(array(sint(1, 4)), ArrayType)
def test_bits(): assert isinstance(bits(1, 4), BitsType) assert isinstance(bits([1, 0, 0, 0]), BitsType) assert isinstance(bits(VCC), BitsType) assert isinstance(bits(array(1, 4)), BitsType) assert isinstance(bits(uint(1, 4)), BitsType) assert isinstance(bits(sint(1, 4)), BitsType)
def test_tuple(): assert isinstance(tuple_(OrderedDict(x=0, y=1)), TupleType) assert isinstance(tuple_([0, 1]), TupleType) assert isinstance(tuple_(VCC), TupleType) assert isinstance(tuple_(array(1, 4)), TupleType) assert isinstance(tuple_(bits(1, 4)), TupleType) assert isinstance(tuple_(sint(1, 4)), TupleType) assert isinstance(tuple_(uint(1, 4)), TupleType)
def wrapper(*args, **kwargs): retval = fn(*args, **kwargs) T = type(args[0]) if issubclass(T, m.UInt): return m.uint(retval) elif issubclass(T, m.SInt): return m.sint(retval) return retval
def __init__(self, x_len): super().__init__(x_len) io = self.io eq = io.rs1 == io.rs2 neq = ~eq lt = m.sint(io.rs1) < m.sint(io.rs2) ge = ~lt ltu = io.rs1 < io.rs2 geu = ~ltu io.taken @= ( ((io.br_type == BR_EQ) & eq) | ((io.br_type == BR_NE) & neq) | ((io.br_type == BR_LT) & lt) | ((io.br_type == BR_GE) & ge) | ((io.br_type == BR_LTU) & ltu) | ((io.br_type == BR_GEU) & geu) )
def wrapper(*args, **kwargs): retval = fn(*args, **kwargs) T = type(args[0]) if isinstance(T, m.UIntKind): return m.uint(retval) elif isinstance(T, m.SIntKind): return m.sint(retval) return retval
def test_clock(): assert isinstance(clock(0), ClockType) assert isinstance(clock(1), ClockType) assert isinstance(clock(VCC), ClockType) assert isinstance(clock(GND), ClockType) assert isinstance(clock(bit(0)), ClockType) assert isinstance(clock(clock(0)), ClockType) assert isinstance(clock(reset(0)), ClockType) assert isinstance(clock(enable(0)), ClockType) assert isinstance(clock(bits(0, 1)), ClockType) assert isinstance(clock(uint(0, 1)), ClockType) assert isinstance(clock(sint(0, 1)), ClockType)
def test_reset(): assert isinstance(reset(0), ResetType) assert isinstance(reset(1), ResetType) assert isinstance(reset(VCC), ResetType) assert isinstance(reset(GND), ResetType) assert isinstance(reset(bit(0)), ResetType) assert isinstance(reset(clock(0)), ResetType) assert isinstance(reset(enable(0)), ResetType) assert isinstance(reset(reset(0)), ResetType) assert isinstance(reset(bits(0, 1)), ResetType) assert isinstance(reset(uint(0, 1)), ResetType) assert isinstance(reset(sint(0, 1)), ResetType)
def test_enable(): assert isinstance(enable(0), EnableType) assert isinstance(enable(1), EnableType) assert isinstance(enable(VCC), EnableType) assert isinstance(enable(GND), EnableType) assert isinstance(enable(bit(0)), EnableType) assert isinstance(enable(clock(0)), EnableType) assert isinstance(enable(reset(0)), EnableType) assert isinstance(enable(enable(0)), EnableType) assert isinstance(enable(bits(0, 1)), EnableType) assert isinstance(enable(uint(0, 1)), EnableType) assert isinstance(enable(sint(0, 1)), EnableType)
def __init__(self, x_len, n_ways: int, n_sets: int, b_bytes: int): b_bits = b_bytes << 3 b_len = m.bitutils.clog2(b_bytes) s_len = m.bitutils.clog2(n_sets) t_len = x_len - (s_len + b_len) n_words = b_bits // x_len w_bytes = x_len // 8 byte_offset_bits = m.bitutils.clog2(w_bytes) nasti_params = NastiParameters(data_bits=64, addr_bits=x_len, id_bits=5) data_beats = b_bits // nasti_params.x_data_bits class MetaData(m.Product): tag = m.UInt[t_len] self.io = m.IO(**make_cache_ports(x_len, nasti_params)) self.io += m.ClockIO() class State(m.Enum): IDLE = 0 READ_CACHE = 1 WRITE_CACHE = 2 WRITE_BACK = 3 WRITE_ACK = 4 REFILL_READY = 5 REFILL = 6 state = m.Register(init=State.IDLE)() # memory v = m.Register(m.UInt[n_sets], has_enable=True)() d = m.Register(m.UInt[n_sets], has_enable=True)() meta_mem = m.Memory(n_sets, MetaData, read_latency=1, has_read_enable=True)() data_mem = [ ArrayMaskMem(n_sets, w_bytes, m.UInt[8], read_latency=1, has_read_enable=True)() for _ in range(n_words) ] addr_reg = m.Register(type(self.io.cpu.req.data.addr).undirected_t, has_enable=True)() cpu_data = m.Register(type(self.io.cpu.req.data.data).undirected_t, has_enable=True)() cpu_mask = m.Register(type(self.io.cpu.req.data.mask).undirected_t, has_enable=True)() self.io.nasti.r.ready @= state.O == State.REFILL # Counters assert data_beats > 0 if data_beats > 1: read_counter = mantle.CounterModM(data_beats, max(data_beats.bit_length(), 1), has_ce=True) read_counter.CE @= m.enable(self.io.nasti.r.fired()) read_count, read_wrap_out = read_counter.O, read_counter.COUT write_counter = mantle.CounterModM(data_beats, max(data_beats.bit_length(), 1), has_ce=True) write_count, write_wrap_out = write_counter.O, write_counter.COUT else: read_count, read_wrap_out = 0, 1 write_count, write_wrap_out = 0, 1 refill_buf = m.Register(m.Array[data_beats, m.UInt[nasti_params.x_data_bits]], has_enable=True)() if data_beats == 1: refill_buf.I[0] @= self.io.nasti.r.data.data else: refill_buf.I @= m.set_index(refill_buf.O, self.io.nasti.r.data.data, read_count[:-1]) refill_buf.CE @= m.enable(self.io.nasti.r.fired()) is_idle = state.O == State.IDLE is_read = state.O == State.READ_CACHE is_write = state.O == State.WRITE_CACHE is_alloc = (state.O == State.REFILL) & read_wrap_out # m.display("[%0t]: is_alloc = %x", m.time(), is_alloc)\ # .when(m.posedge(self.io.CLK)) is_alloc_reg = m.Register(m.Bit)()(is_alloc) hit = m.Bit(name="hit") wen = is_write & (hit | is_alloc_reg) & ~self.io.cpu.abort | is_alloc # m.display("[%0t]: wen = %x", m.time(), wen)\ # .when(m.posedge(self.io.CLK)) ren = m.enable(~wen & (is_idle | is_read) & self.io.cpu.req.valid) ren_reg = m.enable(m.Register(m.Bit)()(ren)) addr = self.io.cpu.req.data.addr idx = addr[b_len:s_len + b_len] tag_reg = addr_reg.O[s_len + b_len:x_len] idx_reg = addr_reg.O[b_len:s_len + b_len] off_reg = addr_reg.O[byte_offset_bits:b_len] rmeta = meta_mem.read(idx, ren) rdata = m.concat(*(mem.read(idx, ren) for mem in data_mem)) rdata_buf = m.Register(type(rdata), has_enable=True)()(rdata, CE=ren_reg) read = m.mux([ m.as_bits(m.mux([rdata_buf, rdata], ren_reg)), m.as_bits(refill_buf.O) ], is_alloc_reg) # m.display("is_alloc_reg=%x", is_alloc_reg)\ # .when(m.posedge(self.io.CLK)) hit @= v.O[idx_reg] & (rmeta.tag == tag_reg) # read mux self.io.cpu.resp.data.data @= m.array( [read[i * x_len:(i + 1) * x_len] for i in range(n_words)])[off_reg] self.io.cpu.resp.valid @= (is_idle | (is_read & hit) | (is_alloc_reg & ~cpu_mask.O.reduce_or())) m.display("resp.valid=%x", self.io.cpu.resp.valid.value())\ .when(m.posedge(self.io.CLK)) m.display("[%0t]: valid = %x", m.time(), self.io.cpu.resp.valid.value())\ .when(m.posedge(self.io.CLK)) m.display("[%0t]: is_idle = %x, is_read = %x, hit = %x, is_alloc_reg = " "%x, ~cpu_mask.O.reduce_or() = %x", m.time(), is_idle, is_read, hit, is_alloc_reg, ~cpu_mask.O.reduce_or())\ .when(m.posedge(self.io.CLK)) m.display("[%0t]: refill_buf.O=%x, %x", m.time(), *refill_buf.O)\ .when(m.posedge(self.io.CLK))\ .if_(self.io.cpu.resp.valid.value() & is_alloc_reg) m.display("[%0t]: read=%x", m.time(), read)\ .when(m.posedge(self.io.CLK))\ .if_(self.io.cpu.resp.valid.value() & is_alloc_reg) addr_reg.I @= addr addr_reg.CE @= m.enable(self.io.cpu.resp.valid.value()) cpu_data.I @= self.io.cpu.req.data.data cpu_data.CE @= m.enable(self.io.cpu.resp.valid.value()) cpu_mask.I @= self.io.cpu.req.data.mask cpu_mask.CE @= m.enable(self.io.cpu.resp.valid.value()) wmeta = MetaData(name="wmeta") wmeta.tag @= tag_reg offset_mask = (m.zext_to(cpu_mask.O, w_bytes * 8) << m.concat( m.bits(0, byte_offset_bits), off_reg)) wmask = m.mux([m.SInt[w_bytes * 8](-1), m.sint(offset_mask)], ~is_alloc) if len(refill_buf.O) == 1: wdata_alloc = self.io.nasti.r.data.data else: wdata_alloc = m.concat( # TODO: not sure why they use `init.reverse` # https://github.com/ucb-bar/riscv-mini/blob/release/src/main/scala/Cache.scala#L116 m.concat(*refill_buf.O[:-1]), self.io.nasti.r.data.data) wdata = m.mux([wdata_alloc, m.as_bits(m.repeat(cpu_data.O, n_words))], ~is_alloc) v.I @= m.set_index(v.O, m.bit(True), idx_reg) v.CE @= m.enable(wen) d.I @= m.set_index(d.O, ~is_alloc, idx_reg) d.CE @= m.enable(wen) # m.display("[%0t]: refill_buf.O = %x", m.time(), # m.concat(*refill_buf.O)).when(m.posedge(self.io.CLK)).if_(wen) # m.display("[%0t]: nasti.r.data.data = %x", m.time(), # self.io.nasti.r.data.data).when(m.posedge(self.io.CLK)).if_(wen) meta_mem.write(wmeta, idx_reg, m.enable(wen & is_alloc)) for i, mem in enumerate(data_mem): data = [ wdata[i * x_len + j * 8:i * x_len + (j + 1) * 8] for j in range(w_bytes) ] mem.write(m.array(data), idx_reg, wmask[i * w_bytes:(i + 1) * w_bytes], m.enable(wen)) # m.display("[%0t]: wdata = %x, %x, %x, %x", m.time(), # *mem.WDATA.value()).when(m.posedge(self.io.CLK)).if_(wen) # m.display("[%0t]: wmask = %x, %x, %x, %x", m.time(), # *mem.WMASK.value()).when(m.posedge(self.io.CLK)).if_(wen) tag_and_idx = m.zext_to(m.concat(idx_reg, tag_reg), nasti_params.x_addr_bits) self.io.nasti.ar.data @= NastiReadAddressChannel( nasti_params, 0, tag_and_idx << m.Bits[len(tag_and_idx)](b_len), m.bitutils.clog2(nasti_params.x_data_bits // 8), data_beats - 1) rmeta_and_idx = m.zext_to(m.concat(idx_reg, rmeta.tag), nasti_params.x_addr_bits) self.io.nasti.aw.data @= NastiWriteAddressChannel( nasti_params, 0, rmeta_and_idx << m.Bits[len(rmeta_and_idx)](b_len), m.bitutils.clog2(nasti_params.x_data_bits // 8), data_beats - 1) self.io.nasti.w.data @= NastiWriteDataChannel( nasti_params, m.array([ read[i * nasti_params.x_data_bits:(i + 1) * nasti_params.x_data_bits] for i in range(data_beats) ])[write_count[:-1]], None, write_wrap_out) is_dirty = v.O[idx_reg] & d.O[idx_reg] # TODO: Have to use temporary so we can invoke `fired()` aw_valid = m.Bit(name="aw_valid") self.io.nasti.aw.valid @= aw_valid ar_valid = m.Bit(name="ar_valid") self.io.nasti.ar.valid @= ar_valid b_ready = m.Bit(name="b_ready") self.io.nasti.b.ready @= b_ready @m.inline_combinational() def logic(): state.I @= state.O aw_valid @= False ar_valid @= False self.io.nasti.w.valid @= False b_ready @= False if state.O == State.IDLE: if self.io.cpu.req.valid: if self.io.cpu.req.data.mask.reduce_or(): state.I @= State.WRITE_CACHE else: state.I @= State.READ_CACHE elif state.O == State.READ_CACHE: if hit: if self.io.cpu.req.valid: if self.io.cpu.req.data.mask.reduce_or(): state.I @= State.WRITE_CACHE else: state.I @= State.READ_CACHE else: state.I @= State.IDLE else: aw_valid @= is_dirty ar_valid @= ~is_dirty if self.io.nasti.aw.fired(): state.I @= State.WRITE_BACK elif self.io.nasti.ar.fired(): state.I @= State.REFILL elif state.O == State.WRITE_CACHE: if hit | is_alloc_reg | self.io.cpu.abort: state.I @= State.IDLE else: aw_valid @= is_dirty ar_valid @= ~is_dirty if self.io.nasti.aw.fired(): state.I @= State.WRITE_BACK elif self.io.nasti.ar.fired(): state.I @= State.REFILL elif state.O == State.WRITE_BACK: self.io.nasti.w.valid @= True if write_wrap_out: state.I @= State.WRITE_ACK elif state.O == State.WRITE_ACK: b_ready @= True if self.io.nasti.b.fired(): state.I @= State.REFILL_READY elif state.O == State.REFILL_READY: ar_valid @= True if self.io.nasti.ar.fired(): state.I @= State.REFILL elif state.O == State.REFILL: if read_wrap_out: if cpu_mask.O.reduce_or(): state.I @= State.WRITE_CACHE else: state.I @= State.IDLE if data_beats > 1: # TODO: Have to do this at the end since the inline comb logic # wires up nasti.w write_counter.CE @= m.enable(self.io.nasti.w.fired())
from magma import sint, bits, concat, wire, compile, EndCircuit from mantle import SLE from loam.boards.icestick import IceStick icestick = IceStick() for i in range(4): icestick.J1[i].input().on() icestick.D1.on() main = icestick.main() A = sint(concat(main.J1[0:2], bits(0, 6))) B = sint(concat(main.J1[2:4], bits(0, 6))) O = main.D1 sle = SLE(8) wire(sle(A, B), main.D1) EndCircuit()
def __init__(self, x_len, ALU=ALUArea, ImmGen=ImmGenWire, BrCond=BrCondArea): self.io = make_DatapathIO(x_len) + m.ClockIO(has_reset=True) csr = CSRGen(x_len)() reg_file = RegFile(x_len)() alu = ALU(x_len)() imm_gen = ImmGen(x_len)() br_cond = BrCondArea(x_len)() # Fetch / Execute Registers fe_inst = m.Register(init=Instructions.NOP, has_enable=True)() fe_pc = m.Register(m.UInt[x_len], has_enable=True)() # Execute / Write Back Registers ew_inst = m.Register(init=Instructions.NOP)() ew_pc = m.Register(m.UInt[x_len])() ew_alu = m.Register(m.UInt[x_len])() csr_in = m.Register(m.UInt[x_len])() # Control signals st_type = m.Register(type(self.io.ctrl.st_type).undirected_t)() ld_type = m.Register(type(self.io.ctrl.ld_type).undirected_t)() wb_sel = m.Register(type(self.io.ctrl.wb_sel).undirected_t)() wb_en = m.Register(m.Bit)() csr_cmd = m.Register(type(self.io.ctrl.csr_cmd).undirected_t)() illegal = m.Register(m.Bit)() pc_check = m.Register(m.Bit)() # Fetch started = m.Register(m.Bit)()(m.bit(self.io.RESET)) stall = ~self.io.icache.resp.valid | ~self.io.dcache.resp.valid pc = m.Register(init=UIntVector[x_len](Const.PC_START) - UIntVector[x_len](4))() npc = m.mux([ m.mux([ m.mux([ m.mux([ m.mux([pc.O + m.uint(4, x_len), pc.O], self.io.ctrl.pc_sel == PC_0), alu.sum_ >> 1 << 1 ], (self.io.ctrl.pc_sel == PC_ALU) | br_cond.taken), csr.epc ], self.io.ctrl.pc_sel == PC_EPC), csr.evec ], csr.expt), pc.O ], stall) inst = m.mux([self.io.icache.resp.data.data, Instructions.NOP], started | self.io.ctrl.inst_kill | br_cond.taken | csr.expt) pc.I @= npc self.io.icache.req.data.addr @= npc self.io.icache.req.data.data @= 0 self.io.icache.req.data.mask @= 0 self.io.icache.req.valid @= ~stall self.io.icache.abort @= False fe_pc.I @= pc.O fe_pc.CE @= m.enable(~stall) fe_inst.I @= inst fe_inst.CE @= m.enable(~stall) # Execute # Decode self.io.ctrl.inst @= fe_inst.O # reg_file read rs1_addr = fe_inst.O[15:20] rs2_addr = fe_inst.O[20:25] reg_file.raddr1 @= rs1_addr reg_file.raddr2 @= rs2_addr # gen immediates imm_gen.inst @= fe_inst.O imm_gen.sel @= self.io.ctrl.imm_sel # bypass wb_rd_addr = ew_inst.O[7:12] rs1_hazard = wb_en.O & rs1_addr.reduce_or() & (rs1_addr == wb_rd_addr) rs2_hazard = wb_en.O & rs2_addr.reduce_or() & (rs2_addr == wb_rd_addr) rs1 = m.mux([reg_file.rdata1, ew_alu.O], (wb_sel.O == WB_ALU) & rs1_hazard) rs2 = m.mux([reg_file.rdata2, ew_alu.O], (wb_sel.O == WB_ALU) & rs2_hazard) # ALU operations alu.A @= m.mux([fe_pc.O, rs1], self.io.ctrl.A_sel == A_RS1) alu.B @= m.mux([imm_gen.O, rs2], self.io.ctrl.B_sel == B_RS2) alu.op @= self.io.ctrl.alu_op # Branch condition calc br_cond.rs1 @= rs1 br_cond.rs2 @= rs2 br_cond.br_type @= self.io.ctrl.br_type # D$ access daddr = m.mux([alu.sum_, ew_alu.O], stall) >> 2 << 2 w_offset = ((m.bits(alu.sum_[1], x_len) << 4) | (m.bits(alu.sum_[0], x_len) << 3)) self.io.dcache.req.valid @= ~stall & (self.io.ctrl.st_type.reduce_or() | self.io.ctrl.ld_type.reduce_or()) self.io.dcache.req.data.addr @= daddr self.io.dcache.req.data.data @= rs2 << w_offset self.io.dcache.req.data.mask @= m.dict_lookup( { ST_SW: m.bits(0b1111, 4), ST_SH: m.bits(0b11, 4) << m.zext(alu.sum_[0:2], 2), ST_SB: m.bits(0b1, 4) << m.zext(alu.sum_[0:2], 2), }, m.mux([self.io.ctrl.st_type, st_type.O], stall), m.bits(0, 4)) # Pipelining @m.inline_combinational() def pipeline_logic(): ew_pc.I @= ew_pc.O ew_inst.I @= ew_inst.O ew_alu.I @= ew_alu.O csr_in.I @= csr_in.O st_type.I @= st_type.O ld_type.I @= ld_type.O wb_sel.I @= wb_sel.O wb_en.I @= wb_en.O csr_cmd.I @= csr_cmd.O illegal.I @= illegal.O pc_check.I @= pc_check.O if m.bit(self.io.RESET) | ~stall & csr.expt: st_type.I @= 0 ld_type.I @= 0 wb_en.I @= 0 csr_cmd.I @= 0 illegal.I @= False pc_check.I @= False elif ~stall & ~csr.expt: ew_pc.I @= fe_pc.O ew_inst.I @= fe_inst.O ew_alu.I @= alu.O csr_in.I @= m.mux([rs1, imm_gen.O], self.io.ctrl.imm_sel == IMM_Z) st_type.I @= self.io.ctrl.st_type ld_type.I @= self.io.ctrl.ld_type wb_sel.I @= self.io.ctrl.wb_sel wb_en.I @= self.io.ctrl.wb_en csr_cmd.I @= self.io.ctrl.csr_cmd illegal.I @= self.io.ctrl.illegal pc_check.I @= self.io.ctrl.pc_sel == PC_ALU # Load l_offset = ((m.uint(ew_alu.O[1], x_len) << 4) | (m.uint(ew_alu.O[0], x_len) << 3)) l_shift = self.io.dcache.resp.data.data >> l_offset load = m.dict_lookup( { LD_LH: m.sext_to(m.sint(l_shift[0:16]), x_len), LD_LHU: m.sint(m.zext_to(l_shift[0:16], x_len)), LD_LB: m.sext_to(m.sint(l_shift[0:8]), x_len), LD_LBU: m.sint(m.zext_to(l_shift[0:8], x_len)) }, ld_type.O, m.sint(self.io.dcache.resp.data.data)) # CSR access csr.stall @= stall csr.I @= csr_in.O csr.cmd @= csr_cmd.O csr.inst @= ew_inst.O csr.pc @= ew_pc.O csr.addr @= ew_alu.O csr.illegal @= illegal.O csr.pc_check @= pc_check.O csr.ld_type @= ld_type.O csr.st_type @= st_type.O self.io.host @= csr.host # Regfile write reg_write = m.dict_lookup( { WB_MEM: m.uint(load), WB_PC4: (ew_pc.O + 4), WB_CSR: csr.O }, wb_sel.O, ew_alu.O) reg_file.wen @= m.enable(wb_en.O & ~stall & ~csr.expt) reg_file.waddr @= wb_rd_addr reg_file.wdata @= reg_write # Abort store when there's an exception self.io.dcache.abort @= csr.expt
def test_sint(): assert isinstance(sint(1, 4), SIntType) assert isinstance(sint([1, 0, 0, 0]), SIntType) assert isinstance(sint(VCC), SIntType) assert isinstance(sint(array(1, 4)), SIntType) assert isinstance(sint(bits(1, 4)), SIntType)