def test_optional_assignment(target): EQ = m.DefineCircuit("eq", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) m.wire(0, EQ.O) m.EndDefine() @m.circuit.combinational def logic(a: m.Bit) -> (m.Bit, m.Bit): d = m.bit(1) if EQ()(a, m.bit(0)): c = m.bit(1) else: c = m.bit(0) d = m.bit(1) return (c, d) class Foo(m.Circuit): IO = ["a", m.In(m.Bit), "c", m.Out(m.Bit), "d", m.Out(m.Bit)] @classmethod def definition(io): c, d = logic(io.a) m.wire(c, io.c) m.wire(d, io.d) compile_and_check("optional_assignment", Foo, target)
def test_hash_verilog(): [foo0] = m.DefineFromVerilog(""" module foo(input I, output O); assign O = I; endmodule""") foo1 = m.DefineCircuit("foo", "I", m.In(m.Bit), "O", m.Out(m.Bit)) m.EndCircuit() top = m.DefineCircuit("top", "I", m.In(m.Bit), "O", m.Out(m.Bit)) foo0_inst = foo0() foo1_inst = foo1() m.wire(top.I, foo0_inst.I) m.wire(foo0_inst.O, foo1_inst.I) m.wire(foo1_inst.O, top.O) m.EndDefine() assert repr(foo0) == repr(foo1) # Run the uniquification pass as a mechanism to check that foo0 and foo1 # hash to two different things even though they have the same repr. pass_ = m.UniquificationPass(top, None) pass_._run(top) foo_seen = pass_.seen["foo"] assert len(foo_seen) == 2 for v in foo_seen.values(): assert len(v) == 1 expected_ids_ = {id(v[0]) for v in foo_seen.values()} ids_ = {id(foo0), id(foo1)} assert expected_ids_ == ids_
def test_include_verilog(target, simulator): SB_DFF = m.DeclareCircuit('SB_DFF', "D", m.In(m.Bit), "Q", m.Out(m.Bit), "C", m.In(m.Clock)) main = m.DefineCircuit('main', "I", m.In(m.Bit), "O", m.Out(m.Bit), *m.ClockInterface()) ff = SB_DFF() m.wire(ff.D, main.I) m.wire(ff.Q, main.O) m.EndDefine() tester = fault.Tester(main, main.CLK) tester.poke(main.CLK, 0) tester.poke(main.I, 1) tester.eval() tester.expect(main.O, 0) tester.step(2) tester.expect(main.O, 1) sb_dff_filename = pathlib.Path("tests/sb_dff_sim.v").resolve() kwargs = {} if simulator is not None: kwargs["simulator"] = simulator with tempfile.TemporaryDirectory() as tmp_dir: tester.compile_and_run(target=target, directory=tmp_dir, include_verilog_libraries=[sb_dff_filename], **kwargs) if target in ["verilator"]: # Should work by including the tests/ directory which contains the # verilog file SB_DFF.v dir_path = os.path.dirname(os.path.realpath(__file__)) with tempfile.TemporaryDirectory() as tmp_dir: tester.compile_and_run(target=target, directory=tmp_dir, include_directories=[dir_path], **kwargs)
def create_io1out_pad(): cb = m.DefineCircuit("io1out_pad", "clk", m.In(m.Clock), "rst", m.In(m.Reset), "config_data", m.In(m.Bits(32)), "config_addr", m.In(m.Bits(32)), "tile_id", m.In(m.Bits(16)), "pin_0", m.In(m.Bit), "pin_1", m.In(m.Bit), "pin_2", m.In(m.Bit), "pin_3", m.In(m.Bit), "top_pin", m.Out(m.Bits(1))) # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) addr_match = mantle.EQ(16) m.wire(addr_match.I0, cb.config_addr[0:16]) m.wire(addr_match.I1, cb.tile_id) m.wire(addr_match.O, config_reg.CE) m.wire(cb.config_data, config_reg.I) m.wire(cb.clk, config_reg.CLK) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], cb.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Config mux config_mux = mantle.Mux(height=4, width=1) m.wire(config_mux.O, cb.top_pin) m.wire(config_mux.S, config_reg.O[0:2]) m.wire(cb.pin_0, config_mux.I0[0]) m.wire(cb.pin_1, config_mux.I1[0]) m.wire(cb.pin_2, config_mux.I2[0]) m.wire(cb.pin_3, config_mux.I3[0]) m.EndDefine() return cb
def test_multiple_assign(target): EQ = m.DefineCircuit("eq", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) m.wire(0, EQ.O) m.EndDefine() @m.circuit.combinational def logic(a: m.Bit) -> (m.Bit,): if EQ()(a, m.bit(0)): c = m.bit(1) c = m.bit(0) else: c = m.bit(0) c = m.bit(1) return (c,) class Foo(m.Circuit): IO = ["a", m.In(m.Bit), "c", m.Out(m.Bit)] @classmethod def definition(io): c = logic(io.a) m.wire(c, io.c) compile_and_check("multiple_assign", Foo, target)
def test_binary_primitive(binary_primitive, width): primitive_name, primitive_op, signed = binary_primitive prim = m.DeclareCircuit(f"primitive_name", "in0", m.In(m.Array(width, m.Bit)), "in1", m.In(m.Array(width, m.Bit)), "out", m.Out(m.Array(width, m.Bit)), coreir_lib="coreir", coreir_name=primitive_name, coreir_genargs={"width": width}) circ = m.DefineCircuit(f"DesignTop", "I0", m.In(m.Array(width, m.Bit)), "I1", m.In(m.Array(width, m.Bit)), "O", m.Out(m.Array(width, m.Bit))) inst = prim() m.wire(circ.I0, inst.in0) m.wire(circ.I1, inst.in1) m.wire(circ.O, inst.out) m.EndDefine() m.compile(f"build/{primitive_name}", circ, output="coreir") dir_path = os.path.dirname(os.path.realpath(__file__)) result = delegator.run( f"CGRAMapper/bin/cgra-mapper build/{primitive_name}.json build/{primitive_name}_mapped.json", cwd=dir_path) assert not result.return_code, result.out + "\n" + result.err result = delegator.run(f"./CGRAGenerator/bin/generate.csh") assert not result.return_code, result.out + "\n" + result.err result = delegator.run( f"CGRAGenerator/bitstream/bsbuilder/serpent.csh build/{primitive_name}_mapped.json -cgra_info CGRAGenerator/hardware/generator_z/top/cgra_info.txt -o build/{primitive_name}_mapped_annotated" ) assert not result.return_code, result.out + "\n" + result.err
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1, name="ram") waddr = mantle.Counter(2, cout=False) wdata = mantle.Counter(1, cout=False) we = 1 raddr = mantle.Counter(2, cout=False) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA[0], main.rdata) m.EndDefine() if m.mantle_target == "coreir": output = "coreir" suffix = "json" else: output = "verilog" suffix = "v" m.compile(f"build/test_common_ram_{m.mantle_target}", main, output) assert check_files_equal( __file__, f"build/test_common_ram_{m.mantle_target}.{suffix}", f"gold/test_common_ram_{m.mantle_target}.{suffix}")
def test_env_mod(target, simulator): myinv = m.DefineCircuit('myinv', 'a', m.In(m.Bit), 'y', m.Out(m.Bit)) m.wire(~myinv.a, myinv.y) m.EndDefine() tester = fault.InvTester(myinv, in_='a', out='y') tester.compile_and_run(target=target, simulator=simulator, tmp_dir=True)
def test_tester_verilog_wrapped(target, simulator): SimpleALU = m.DefineFromVerilogFile("tests/simple_alu.v", type_map={"CLK": m.In(m.Clock)}, target_modules=["SimpleALU"])[0] circ = m.DefineCircuit("top", "a", m.In(m.Bits[16]), "b", m.In(m.Bits[16]), "c", m.Out(m.Bits[16]), "config_data", m.In(m.Bits[2]), "config_en", m.In(m.Bit), "CLK", m.In(m.Clock)) simple_alu = SimpleALU() m.wire(simple_alu.a, circ.a) m.wire(simple_alu.b, circ.b) m.wire(simple_alu.c, circ.c) m.wire(simple_alu.config_data, circ.config_data) m.wire(simple_alu.config_en, circ.config_en) m.wire(simple_alu.CLK, circ.CLK) m.EndDefine() tester = fault.Tester(circ, circ.CLK) tester.verilator_include("SimpleALU") tester.verilator_include("ConfigReg") tester.circuit.CLK = 0 for i in range(0, 4): tester.poke( fault.WrappedVerilogInternalPort("SimpleALU_inst0.config_reg.Q", m.Bits[2]), i) tester.step(2) tester.expect( fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode", m.Bits[2]), i) signal = tester.peek( fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode", m.Bits[2])) tester.expect( fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode", m.Bits[2]), signal) tester.expect( fault.WrappedVerilogInternalPort( "SimpleALU_inst0.config_reg.Q", m.Bits[2]), i) signal = tester.peek( fault.WrappedVerilogInternalPort( "SimpleALU_inst0.config_reg.Q", m.Bits[2])) tester.expect( fault.WrappedVerilogInternalPort( "SimpleALU_inst0.config_reg.Q", m.Bits[2]), signal) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator)
def test_enum(): class State(m.Enum): zero = 0 one = 1 two = 2 circuit = m.DefineCircuit('enum_test', "I", m.In(State), "O", m.Out(m.Array[2, State])) m.wire(circuit.I, circuit.O[0]) m.wire(State.zero, circuit.O[1]) m.EndDefine() m.compile("build/test_enum", circuit, output="coreir-verilog") assert check_files_equal(__file__, "build/test_enum.v", "gold/test_enum.v")
def create_io1in_pad(): cb = m.DefineCircuit("io1in_pad", "clk", m.In(m.Clock), "rst", m.In(m.Reset), "pin_0", m.Out(m.Bit), "pin_1", m.Out(m.Bit), "pin_2", m.Out(m.Bit), "pin_3", m.Out(m.Bit), "top_pin", m.In(m.Bits(1))) m.wire(cb.pin_0, cb.top_pin[0]) m.wire(cb.pin_1, cb.top_pin[0]) m.wire(cb.pin_2, cb.top_pin[0]) m.wire(cb.pin_3, cb.top_pin[0]) m.EndDefine() return cb
def test_assign(width, output): T = m.util.BitOrBits(width) name = f"test_assign_operator_{width}_{output}" circ = m.DefineCircuit(name, "a", m.In(T), "b", m.In(T), "c", m.Out(T)) and2 = DeclareAnd(width)() and2.I0 <= circ.a and2.I1 <= circ.b circ.c <= and2.O m.EndDefine() m.compile(f"build/{name}", circ, output) suffix = "v" if output == "verilog" else "json" assert check_files_equal(__file__, f"build/{name}.{suffix}", f"gold/{name}.{suffix}")
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1) waddr = mantle.Counter(4) wdata = mantle.Counter(1) we = 1 raddr = mantle.FF()(mantle.Counter(4)) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA, main.rdata) m.EndDefine() m.compile("build/test_common_ram", main)
def to_fpga(rx): icestick = IceStick() icestick.Clock.on() icestick.D1.on() main = icestick.DefineMain() rom = string_to_rom('x' * 16) matcher = Matcher(rx) m.wire(rom, matcher.char) m.wire(matcher.match, main.D1) m.EndDefine() m.compile('regulair', main)
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1) waddr = mantle.Counter(4, cout=False) wdata = mantle.Counter(1, cout=False) we = 1 raddr = mantle.Counter(4, cout=False) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA[0], main.rdata) m.EndDefine() if m.mantle_target == "coreir": output = "coreir" else: output = "verilog" m.compile("build/test_common_ram", main, output)
def test_uniquify_verilog(): [foo0] = m.DefineFromVerilog(""" module foo(input I, output O); assign O = I; endmodule""") [foo1] = m.DefineFromVerilog(""" module foo(input II, output OO); assign OO = II; endmodule""") assert repr(foo0) != repr(foo1) top = m.DefineCircuit("top", "I", m.In(m.Bit), "O", m.Out(m.Bit)) foo0_inst = foo0() foo1_inst = foo1() m.wire(top.I, foo0_inst.I) m.wire(foo0_inst.O, foo1_inst.II) m.wire(foo1_inst.OO, top.O) m.EndDefine() with pytest.raises(Exception) as pytest_e: m.compile(f"top", top, output="coreir") assert False assert pytest_e.type is Exception assert pytest_e.value.args == \ ("Can not rename a verilog wrapped file",)
import magma as m from loam.boards.gpdevboard import GPDevBoard gp = GPDevBoard() gp.fpga.P4.output().on() main = gp.main() m.wire(1, main.P4) m.EndDefine()
def DefineDecode(i, n): circ = m.DefineCircuit(f"Decode{i}{n}", "I", m.In(m.Bits(n)), "O", m.Out(m.Bit)) m.wire(circ.O, EQ(n)(circ.I, m.bits(i, n))) m.EndDefine() return circ
def create_pe_tile(): pe = m.DefineCircuit( "pe_tile", "clk", m.In(m.Clock), "rst", m.In(m.Reset), "config_data", m.In(m.Bits(32)), "config_addr", m.In(m.Bits(32)), "tile_id", m.In(m.Bits(16)), "side_0_track_0_in", m.In(m.Bits(1)), "side_0_track_1_in", m.In(m.Bits(1)), "side_0_track_2_in", m.In(m.Bits(1)), "side_0_track_3_in", m.In(m.Bits(1)), "side_1_track_0_in", m.In(m.Bits(1)), "side_1_track_1_in", m.In(m.Bits(1)), "side_1_track_2_in", m.In(m.Bits(1)), "side_1_track_3_in", m.In(m.Bits(1)), "side_2_track_0_in", m.In(m.Bits(1)), "side_2_track_1_in", m.In(m.Bits(1)), "side_2_track_2_in", m.In(m.Bits(1)), "side_2_track_3_in", m.In(m.Bits(1)), "side_3_track_0_in", m.In(m.Bits(1)), "side_3_track_1_in", m.In(m.Bits(1)), "side_3_track_2_in", m.In(m.Bits(1)), "side_3_track_3_in", m.In(m.Bits(1)), "side_0_track_0_out", m.Out(m.Bits(1)), "side_0_track_1_out", m.Out(m.Bits(1)), "side_0_track_2_out", m.Out(m.Bits(1)), "side_0_track_3_out", m.Out(m.Bits(1)), "side_1_track_0_out", m.Out(m.Bits(1)), "side_1_track_1_out", m.Out(m.Bits(1)), "side_1_track_2_out", m.Out(m.Bits(1)), "side_1_track_3_out", m.Out(m.Bits(1)), "side_2_track_0_out", m.Out(m.Bits(1)), "side_2_track_1_out", m.Out(m.Bits(1)), "side_2_track_2_out", m.Out(m.Bits(1)), "side_2_track_3_out", m.Out(m.Bits(1)), "side_3_track_0_out", m.Out(m.Bits(1)), "side_3_track_1_out", m.Out(m.Bits(1)), "side_3_track_2_out", m.Out( m.Bits(1)), "side_3_track_3_out", m.Out(m.Bits(1))) # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) addr_match = mantle.EQ(16) m.wire(addr_match.I0, pe.config_addr[0:16]) m.wire(addr_match.I1, pe.tile_id) m.wire(addr_match.O, config_reg.CE) m.wire(pe.config_data, config_reg.I) m.wire(pe.clk, config_reg.CLK) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], pe.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Configure sb = 6, cb0 = 4, cb1 = 5, clb = 7 config_cb0_eq = mantle.EQ(16) m.wire(m.uint(4, 16), config_cb0_eq.I0) m.wire(pe.config_addr[16:32], config_cb0_eq.I1) config_cb1_eq = mantle.EQ(16) m.wire(m.uint(5, 16), config_cb1_eq.I0) m.wire(pe.config_addr[16:32], config_cb1_eq.I1) config_clb_eq = mantle.EQ(16) m.wire(m.uint(7, 16), config_clb_eq.I0) m.wire(pe.config_addr[16:32], config_clb_eq.I1) config_sb_eq = mantle.EQ(16) m.wire(m.uint(6, 16), config_sb_eq.I0) m.wire(pe.config_addr[16:32], config_sb_eq.I1) config_cb0 = mantle.And(2, 1) m.wire(config_cb0.I0[0], config_cb0_eq.O) m.wire(config_cb0.I1[0], addr_match.O) config_cb1 = mantle.And(2, 1) m.wire(config_cb1.I0[0], config_cb1_eq.O) m.wire(config_cb1.I1[0], addr_match.O) config_clb = mantle.And(2, 1) m.wire(config_clb.I0[0], config_clb_eq.O) m.wire(config_clb.I1[0], addr_match.O) config_sb = mantle.And(2, 1) m.wire(config_sb.I0[0], config_sb_eq.O) m.wire(config_sb.I1[0], addr_match.O) # Add ands! # # CB0 cb0 = create_connect_box(1)() m.wire(pe.clk, cb0.clk) m.wire(pe.rst, cb0.rst) m.wire(pe.config_data, cb0.config_data) m.wire(config_cb0.O[0], cb0.config_en) # CB1 cb1 = create_connect_box(1)() m.wire(pe.clk, cb1.clk) m.wire(pe.rst, cb1.rst) m.wire(pe.config_data, cb1.config_data) m.wire(config_cb1.O[0], cb1.config_en) # CLB clb = create_clb(1)() m.wire(pe.clk, clb.clk) m.wire(pe.rst, clb.rst) m.wire(pe.config_data, clb.config_data) m.wire(config_clb.O[0], clb.config_en) # Switch box sb = create_switch_box(1)() m.wire(pe.clk, sb.clk) m.wire(pe.rst, sb.rst) m.wire(pe.config_data, sb.config_data) m.wire(config_sb.O[0], sb.config_en) m.wire(clb.result, sb.clb_result) for side in range(0, 4): for track in range(0, 4): m.wire( getattr(pe, 'side_' + str(side) + '_track_' + str(track) + '_in'), getattr(sb, 'side_' + str(side) + '_track_' + str(track) + '_in')) for side in range(0, 4): for track in range(0, 4): m.wire( getattr(pe, 'side_' + str(side) + '_track_' + str(track) + '_out'), getattr(sb, 'side_' + str(side) + '_track_' + str(track) + '_out')) # Wiring up CLB, SB and CBs m.wire(pe.side_0_track_0_in, cb0.track_0_in) m.wire(pe.side_0_track_1_in, cb0.track_1_in) m.wire(pe.side_0_track_2_in, cb0.track_2_in) m.wire(pe.side_0_track_3_in, cb0.track_3_in) m.wire(sb.side_0_track_0_out, cb0.track_0_out) m.wire(sb.side_0_track_1_out, cb0.track_1_out) m.wire(sb.side_0_track_2_out, cb0.track_2_out) m.wire(sb.side_0_track_3_out, cb0.track_3_out) m.wire(cb0.out, clb.operand0) m.wire(pe.side_1_track_0_in, cb1.track_0_in) m.wire(pe.side_1_track_1_in, cb1.track_1_in) m.wire(pe.side_1_track_2_in, cb1.track_2_in) m.wire(pe.side_1_track_3_in, cb1.track_3_in) m.wire(sb.side_1_track_0_out, cb1.track_0_out) m.wire(sb.side_1_track_1_out, cb1.track_1_out) m.wire(sb.side_1_track_2_out, cb1.track_2_out) m.wire(sb.side_1_track_3_out, cb1.track_3_out) m.wire(cb1.out, clb.operand1) m.EndDefine() return pe
def test_key_error(): default_port_mapping = { "I": "in", "I0": "in0", "I1": "in1", "O": "out", "S": "sel", } def DeclareCoreirCircuit(*args, **kwargs): return m.DeclareCircuit(*args, **kwargs, renamed_ports=default_port_mapping) Mux2x6 = m.DefineCircuit("Mux2x6", "I0", m.In(m.Bits[6]), "I1", m.In(m.Bits[6]), "S", m.In(m.Bit), "O", m.Out(m.Bits[6])) mux = DeclareCoreirCircuit( f"coreir_commonlib_mux{2}x{6}", *[ "I", m.In( m.Tuple(data=m.Array[2, m.Bits[6]], sel=m.Bits[m.bitutils.clog2(2)])), "O", m.Out(m.Bits[6]) ], coreir_name="muxn", coreir_lib="commonlib", coreir_genargs={ "width": 6, "N": 2 })() m.wire(Mux2x6.I0, mux.I.data[0]) m.wire(Mux2x6.I1, mux.I.data[1]) m.wire(Mux2x6.S, mux.I.sel[0]) m.wire(mux.O, Mux2x6.O) m.EndDefine() MuxWrapper_2_6 = m.DefineCircuit("MuxWrapper_2_6", "I", m.Array[2, m.In(m.Bits[6])], "S", m.In(m.Bits[1]), "O", m.Out(m.Bits[6])) Mux2x6_inst0 = Mux2x6() m.wire(MuxWrapper_2_6.I[0], Mux2x6_inst0.I0) m.wire(MuxWrapper_2_6.I[1], Mux2x6_inst0.I1) m.wire(MuxWrapper_2_6.S[0], Mux2x6_inst0.S) m.wire(Mux2x6_inst0.O, MuxWrapper_2_6.O) m.EndCircuit() MuxWrapper_2_6_copy = m.DefineCircuit("MuxWrapper_2_6", "I", m.Array[2, m.In(m.Bits[6])], "S", m.In(m.Bits[1]), "O", m.Out(m.Bits[6])) Mux2x6_inst0 = Mux2x6() m.wire(MuxWrapper_2_6_copy.I[0], Mux2x6_inst0.I0) m.wire(MuxWrapper_2_6_copy.I[1], Mux2x6_inst0.I1) m.wire(MuxWrapper_2_6_copy.S[0], Mux2x6_inst0.S) m.wire(Mux2x6_inst0.O, MuxWrapper_2_6_copy.O) m.EndCircuit() MuxWithDefaultWrapper_2_6_19_0 = m.DefineCircuit( "MuxWithDefaultWrapper_2_6_19_0", "I", m.Array[2, m.In(m.Bits[6])], "S", m.In(m.Bits[19]), "O", m.Out(m.Bits[6])) MuxWrapper_2_6_inst0 = MuxWrapper_2_6() MuxWrapper_2_6_inst1 = MuxWrapper_2_6_copy() m.wire(MuxWithDefaultWrapper_2_6_19_0.I, MuxWrapper_2_6_inst0.I) m.wire(MuxWithDefaultWrapper_2_6_19_0.I, MuxWrapper_2_6_inst1.I) m.wire(MuxWithDefaultWrapper_2_6_19_0.S[0], MuxWrapper_2_6_inst0.S[0]) m.wire(MuxWithDefaultWrapper_2_6_19_0.S[0], MuxWrapper_2_6_inst1.S[0]) m.wire(MuxWrapper_2_6_inst1.O, MuxWithDefaultWrapper_2_6_19_0.O) m.EndCircuit() top = MuxWithDefaultWrapper_2_6_19_0 m.compile(f"build/{top.name}", top, output="coreir") assert check_files_equal(__file__, f"build/{top.name}.json", "gold/uniquification_key_error_mux.json")