Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: whitequark/Boneless-CPU
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: bd95dd1fb420
Choose a base ref
...
head repository: whitequark/Boneless-CPU
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0363735ed8ff
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Jul 13, 2019

  1. gateware.{core,decoder}: simplify. NFC.

    Change: 0 LUT.
    
    This used to give worse results without -abc9, but is now OK.
    whitequark committed Jul 13, 2019
    Copy the full SHA
    78089f3 View commit details
  2. gateware.core: simplify BusArbiter.

    Change: -9 LUT.
    whitequark committed Jul 13, 2019
    Copy the full SHA
    63f6804 View commit details
  3. gateware.{core,decoder}: simplify. NFC.

    Change: -13 LUT.
    whitequark committed Jul 13, 2019
    Copy the full SHA
    0363735 View commit details
Showing with 120 additions and 133 deletions.
  1. +77 −105 boneless/gateware/core.py
  2. +43 −28 boneless/gateware/decoder.py
182 changes: 77 additions & 105 deletions boneless/gateware/core.py
Original file line number Diff line number Diff line change
@@ -66,35 +66,13 @@ def elaborate(self, platform):


class BusArbiter(Elaboratable):
class MuxAddr(ControlEnum):
REG = 0b0
PTR = 0b1
x = 0

class MuxReg(ControlEnum):
PC = 0b00
A = 0b01
B = 0b10
SD = 0b11
x = 0

class MuxDir(ControlEnum):
RD = 0b10
WR = 0b11
x = 0b0

class Op(MultiControlEnum, layout={"addr":MuxAddr, "reg":MuxReg, "dir":MuxDir}):
LD_PC = ("REG", "PC", "RD",)
LD_RA = ("REG", "A", "RD",)
LD_RB = ("REG", "B", "RD",)
LD_RSD = ("REG", "SD", "RD",)
ST_RSD = ("REG", "SD", "WR",)
LD_PTR = ("PTR", "x", "RD",)
ST_PTR = ("PTR", "x", "WR",)
x = ("x", "x", "x", )
class Dir(ControlEnum):
LD = 0b0
ST = 0b1

Addr = InstructionDecoder.Addr

def __init__(self):
self.i_pc = Signal(16)
self.i_w = Signal(13)
self.i_ra = Signal(3)
self.i_rb = Signal(3)
@@ -103,11 +81,11 @@ def __init__(self):
self.i_data = Signal(16)
self.o_data = Signal(16)

self.c_op = self.Op.signal()
self.c_en = Signal()
self.c_dir = self.Dir.signal()
self.c_addr = self.Addr.signal()
self.c_xbus = Signal()

self.r_xbus = Signal()

self.o_bus_addr = Signal(16)

self.i_mem_data = Signal(16)
@@ -123,44 +101,34 @@ def __init__(self):
def elaborate(self, platform):
m = Module()

op = self.Op.expand(m, self.c_op)

with m.Switch(op.addr):
with m.Case(self.MuxAddr.REG):
with m.Switch(op.reg):
with m.Case(self.MuxReg.PC):
m.d.comb += self.o_bus_addr.eq(self.i_pc)
with m.Case(self.MuxReg.A):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_ra, self.i_w))
with m.Case(self.MuxReg.B):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_rb, self.i_w))
with m.Case(self.MuxReg.SD):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_rsd, self.i_w))
with m.Switch(op.dir):
with m.Case(self.MuxDir.RD):
m.d.sync += self.r_xbus.eq(0)
m.d.comb += self.o_mem_re.eq(1)
with m.Case(self.MuxDir.WR):
m.d.comb += self.o_mem_we.eq(1)

with m.Case(self.MuxAddr.PTR):
with m.Switch(self.c_addr):
with m.Case(self.Addr.IND):
m.d.comb += self.o_bus_addr.eq(self.i_ptr)
with m.Switch(op.dir):
with m.Case(self.MuxDir.RD):
m.d.sync += self.r_xbus.eq(self.c_xbus)
with m.If(self.c_xbus):
m.d.comb += self.o_ext_re.eq(1)
with m.Else():
m.d.comb += self.o_mem_re.eq(1)
with m.Case(self.MuxDir.WR):
with m.If(self.c_xbus):
m.d.comb += self.o_ext_we.eq(1)
with m.Else():
m.d.comb += self.o_mem_we.eq(1)
with m.Case(self.Addr.RA):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_ra, self.i_w))
with m.Case(self.Addr.RB):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_rb, self.i_w))
with m.Case(self.Addr.RSD):
m.d.comb += self.o_bus_addr.eq(Cat(self.i_rsd, self.i_w))

r_xbus = Signal()
with m.Switch(self.c_dir):
with m.Case(self.Dir.LD):
with m.If(self.c_en):
m.d.sync += r_xbus.eq(self.c_xbus)
with m.If(self.c_xbus):
m.d.comb += self.o_ext_re.eq(self.c_en)
with m.Else():
m.d.comb += self.o_mem_re.eq(self.c_en)
with m.Case(self.Dir.ST):
with m.If(self.c_xbus):
m.d.comb += self.o_ext_we.eq(self.c_en)
with m.Else():
m.d.comb += self.o_mem_we.eq(self.c_en)

m.d.comb += self.o_mem_data.eq(self.i_data)
m.d.comb += self.o_ext_data.eq(self.i_data)
m.d.comb += self.o_data.eq(Mux(self.r_xbus, self.i_ext_data, self.i_mem_data))
m.d.comb += self.o_data.eq(Mux(r_xbus, self.i_ext_data, self.i_mem_data))

return m

@@ -176,7 +144,7 @@ def __init__(self, alsru_cls, reset_pc=0, reset_w=0xffff, memory=None):
self.s_a = Signal(16)
self.r_a = Signal(16)
self.s_b = Signal(16)
self.s_f = Record(self.r_f.layout)
self.s_f = Record.like(self.r_f)

self.r_cycle = Signal(1)
self.o_done = Signal()
@@ -230,21 +198,18 @@ def elaborate(self, platform):

m.submodules.arb = m_arb = self.m_arb
m.d.comb += [
m_arb.i_pc.eq(self.r_pc),
m_arb.i_w .eq(self.r_w),
m_arb.i_rsd.eq(m_dec.o_rsd),
m_arb.i_w .eq(self.r_w),
m_arb.i_ra .eq(m_dec.o_ra),
m_arb.i_rb .eq(m_dec.o_rb),
m_arb.i_rsd.eq(m_dec.o_rsd),
m_arb.i_ptr.eq(self.s_base + m_dec.o_imm16),
m_arb.c_xbus.eq(m_dec.o_xbus),
]

m.submodules.alsru = m_alsru = self.m_alsru
m.d.comb += [
m_alsru.a.eq(self.r_a),
m_alsru.b.eq(self.s_b),
m_alsru.op.eq(m_dec.o_op),
m_arb.i_data.eq(m_alsru.o),
self.s_f.z.eq(m_alsru.o == 0),
self.s_f.s.eq(m_alsru.o[-1]),
self.s_f.c.eq(m_alsru.co),
@@ -272,54 +237,74 @@ def elaborate(self, platform):
m_shift.i_shamt.eq(self.s_b),
]

with m.Switch(m_dec.o_ld_a):
with m.Case(m_dec.LdA.ZERO):
dec_ld_a = m_dec.LdA.expand(m, m_dec.o_ld_a)
with m.Switch(dec_ld_a.mux):
with m.Case(m_dec.OpAMux.ZERO):
m.d.comb += self.s_a.eq(0)
with m.Case(m_dec.LdA.W):
m.d.comb += self.s_a.eq(self.r_w << 3)
with m.Case(m_dec.LdA.PCp1):
with m.Case(m_dec.OpAMux.PCp1):
m.d.comb += self.s_a.eq(m_dec.o_pc_p1)
with m.Case(m_dec.LdX_PTR):
with m.Case(m_dec.OpAMux.W):
m.d.comb += self.s_a.eq(self.r_w << 3)
with m.Case(m_dec.OpAMux.PTR):
m.d.comb += self.s_a.eq(m_arb.o_data)
m.d.sync += self.r_a.eq(self.s_a)

with m.Switch(m_dec.o_ld_b):
with m.Case(m_dec.LdB.IMM):
dec_ld_b = m_dec.LdB.expand(m, m_dec.o_ld_b)
with m.Switch(dec_ld_b.mux):
with m.Case(m_dec.OpBMux.IMM):
m.d.comb += self.s_b.eq(m_dec.o_imm16)
with m.Case(m_dec.LdX_PTR):
with m.Case(m_dec.OpBMux.PTR):
m.d.comb += self.s_b.eq(m_arb.o_data)

dec_st_r = m_dec.StR.expand(m, m_dec.o_st_r)
m.d.comb += m_arb.i_data.eq(m_alsru.o)

with m.FSM():
m.d.comb += m_dec.i_insn.eq(self.r_insn)
m.d.comb += self.s_base.eq(self.r_a)

with m.State("FETCH"):
m.d.comb += m_dec.c_done.eq(1)
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_PC)
m.d.comb += m_arb.i_ptr.eq(self.r_pc)
m.d.comb += m_arb.c_en.eq(1)
m.d.comb += m_arb.c_addr.eq(m_arb.Addr.IND)
m.next = "LOAD-A"

with m.State("LOAD-A"):
m.d.sync += self.r_insn.eq(m_arb.o_data)
m.d.comb += m_dec.i_insn.eq(m_arb.o_data)
with m.Switch(m_dec.o_ld_a):
with m.Case(m_dec.LdA.RSD):
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_RSD)
with m.Case(m_dec.LdA.RA):
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_RA)
m.d.comb += m_arb.c_addr.eq(dec_ld_a.addr)
with m.Switch(dec_ld_a.mux):
with m.Case(m_dec.OpAMux.PTR):
m.d.comb += m_arb.c_en.eq(1)
m.next = "LOAD-B"

with m.State("LOAD-B"):
m.d.comb += self.s_base.eq(self.s_a)
with m.Switch(m_dec.o_ld_b):
with m.Case(m_dec.LdB.IND):
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_PTR)
with m.Case(m_dec.LdB.RSD):
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_RSD)
with m.Case(m_dec.LdB.RB):
m.d.comb += m_arb.c_op.eq(m_arb.Op.LD_RB)
m.d.comb += m_arb.c_addr.eq(dec_ld_b.addr)
with m.Switch(dec_ld_b.addr):
with m.Case(m_arb.Addr.IND):
m.d.comb += m_arb.c_xbus.eq(m_dec.o_xbus)
with m.Switch(dec_ld_b.mux):
with m.Case(m_dec.OpBMux.PTR):
m.d.comb += m_arb.c_en.eq(1)
m.next = "EXECUTE"

with m.State("EXECUTE"):
m.d.comb += m_arb.c_dir.eq(m_arb.Dir.ST)
m.d.comb += m_arb.c_addr.eq(dec_st_r.addr)
with m.Switch(dec_st_r.addr):
with m.Case(m_arb.Addr.IND):
m.d.comb += m_arb.c_xbus.eq(m_dec.o_xbus)
with m.Switch(dec_st_r.mux):
with m.Case(m_dec.OpRMux.PTR):
m.d.comb += m_arb.c_en.eq(1)
with m.If(m_dec.o_st_f.zs):
m.d.sync += self.r_f["z","s"].eq(self.s_f["z","s"])
with m.If(m_dec.o_st_f.cv):
m.d.sync += self.r_f["c","v"].eq(self.s_f["c","v"])
with m.If(m_dec.o_st_w):
m.d.sync += self.r_w.eq(m_alsru.o >> 3)
with m.If(m_dec.o_shift):
m.d.comb += m_shift.c_en.eq(1)
m.d.comb += m_shift.c_load.eq(self.r_cycle == 0)
@@ -328,19 +313,6 @@ def elaborate(self, platform):
m.d.comb += self.o_done.eq(self.r_cycle == 1)
with m.Else():
m.d.comb += self.o_done.eq(1)
with m.Switch(m_dec.o_st_r):
with m.Case(m_dec.StR.IND):
m.d.comb += m_arb.c_op.eq(m_arb.Op.ST_PTR)
with m.Case(m_dec.StR.RSD):
m.d.comb += m_arb.c_op.eq(m_arb.Op.ST_RSD)
with m.Switch(m_dec.o_st_f):
with m.Case(m_dec.StF.ZS):
m.d.sync += self.r_f["z","s"].eq(self.s_f["z","s"])
with m.Case(m_dec.StF.ZSCV):
m.d.sync += self.r_f["z","s"].eq(self.s_f["z","s"])
m.d.sync += self.r_f["c","v"].eq(self.s_f["c","v"])
with m.If(m_dec.o_st_w):
m.d.sync += self.r_w.eq(m_alsru.o >> 3)
with m.If(self.o_done):
with m.If(m_dec.o_st_pc):
m.d.sync += self.r_pc.eq(m_alsru.o)
71 changes: 43 additions & 28 deletions boneless/gateware/decoder.py
Original file line number Diff line number Diff line change
@@ -71,30 +71,44 @@ def elaborate(self, platform):


class InstructionDecoder(Elaboratable):
LdX_PTR = "1--"

class LdA(ControlEnum):
ZERO = 0b0_00
W = 0b0_01
PCp1 = 0b0_10
RSD = 0b1_01
RA = 0b1_10

class LdB(ControlEnum):
IMM = 0b0_11
IND = 0b1_00
RSD = 0b1_01
RB = 0b1_11

class StR(ControlEnum):
x = 0b0_00
IND = 0b1_00
RSD = 0b1_01

class StF(ControlEnum):
class Addr(ControlEnum):
IND = 0b00
RSD = 0b01
RB = 0b10
RA = 0b11
x = 0b00
ZS = 0b01
ZSCV = 0b11

class OpAMux(ControlEnum):
ZERO = 0b00
PCp1 = 0b01
W = 0b10
PTR = 0b11

class OpBMux(ControlEnum):
IMM = 0b0
PTR = 0b1

class OpRMux(ControlEnum):
ZERO = 0b0
PTR = 0b1

class LdA(MultiControlEnum, layout={"mux":OpAMux, "addr":Addr}):
ZERO = ("ZERO", "x" )
PCp1 = ("PCp1", "x" )
W = ("W", "x" )
RA = ("PTR", "RA" )
RSD = ("PTR", "RSD")

class LdB(MultiControlEnum, layout={"mux":OpBMux, "addr":Addr}):
IMM = ("IMM", "x" )
IND = ("PTR", "IND")
RB = ("PTR", "RB" )
RSD = ("PTR", "RSD")

class StR(MultiControlEnum, layout={"mux":OpRMux, "addr":Addr}):
x = ("ZERO", "x" )
IND = ("PTR", "IND")
RSD = ("PTR", "RSD")

class CI(ControlEnum):
ZERO = 0b00
@@ -149,7 +163,7 @@ def __init__(self, alsru_cls):
self.o_ld_a = self.LdA.signal()
self.o_ld_b = self.LdB.signal()
self.o_st_r = self.StR.signal()
self.o_st_f = self.StF.signal()
self.o_st_f = Record([("zs", 1), ("cv", 1)])
self.o_st_w = Signal()
self.o_st_pc = Signal()

@@ -217,7 +231,7 @@ def elaborate(self, platform):
m_imm.c_width.eq(m_imm.Width.IMM3),
self.o_ld_a.eq(self.LdA.RA),
self.o_st_r.eq(self.StR.RSD),
self.o_st_f.eq(self.StF.ZS),
self.o_st_f.zs.eq(1),
]
with m.Switch(self.i_insn):
with m.Case(opcode.M_RRR.coding):
@@ -242,15 +256,16 @@ def elaborate(self, platform):
self.o_ci.eq(self.CI.ONE),
self.o_op.eq(alsru_cls.Op.AmB),
self.o_st_r.eq(self.StR.x),
self.o_st_f.eq(self.StF.ZSCV),
self.o_st_f.cv.eq(1),
]

with m.Case(opcode.C_ARITH.coding):
m.d.comb += [
m_imm.c_width.eq(m_imm.Width.IMM3),
self.o_ld_a.eq(self.LdA.RA),
self.o_st_r.eq(self.StR.RSD),
self.o_st_f.eq(self.StF.ZSCV),
self.o_st_f.zs.eq(1),
self.o_st_f.cv.eq(1),
]
with m.Switch(self.i_insn):
with m.Case(opcode.M_RRR.coding):
@@ -285,7 +300,7 @@ def elaborate(self, platform):
self.o_shift.eq(1),
self.o_ld_a.eq(self.LdA.RA),
self.o_st_r.eq(self.StR.RSD),
self.o_st_f.eq(self.StF.ZS),
self.o_st_f.zs.eq(1),
]
with m.Switch(self.i_insn):
with m.Case(opcode.M_RRR.coding):