1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package hat.codebuilders;
 26 
 27 import hat.Config;
 28 import hat.FFIConfigCreator;
 29 import optkl.codebuilders.C99CodeBuilder;
 30 import optkl.codebuilders.ScopedCodeBuilderContext;
 31 import optkl.util.Mutable;
 32 
 33 import java.lang.invoke.MethodHandles;
 34 import java.text.SimpleDateFormat;
 35 import java.util.Date;
 36 
 37 public  class C99HATConfigBuilder extends C99CodeBuilder<C99HATConfigBuilder> {
 38 
 39     public C99HATConfigBuilder(ScopedCodeBuilderContext scopedCodeBuilderContext) {
 40         super(scopedCodeBuilderContext);
 41     }
 42 
 43     public final  C99HATConfigBuilder staticConstInt(String name, int padWidth, int value) {
 44         staticKeyword().space().constexprKeyword().space().s32Type().space().identifier(name, padWidth).space().equals().space().intHexValue(value).semicolon().nl();
 45         return this;
 46     }
 47 
 48     public final C99HATConfigBuilder staticConstIntShiftedOne(String name, int padWidth, int shift) {
 49         staticKeyword().space().constexprKeyword().space().s32Type().space().identifier(name, padWidth).space().equals().space().intValue(1).leftShift().intHexValue(shift).semicolon().nl();
 50         return this;
 51     }
 52 
 53     public final C99HATConfigBuilder className() {
 54         return identifier("BasicConfig");
 55     }
 56 
 57     public final C99HATConfigBuilder bitNamesVar() {
 58         return identifier("bitNames");
 59     }
 60 
 61     public final C99HATConfigBuilder bitDescriptionsVar() {
 62         return identifier("bitDescriptions");
 63     }
 64 
 65     public final C99HATConfigBuilder configBitsVar() {
 66         return identifier("configBits");
 67     }
 68 
 69     public final C99HATConfigBuilder configBitsAnd() {
 70         return configBitsVar().space().ampersand().space();
 71     }
 72 
 73     public final C99HATConfigBuilder configBitsAndBitName(String bitName) {
 74         return configBitsAnd().identifier(bitName + "_BIT");
 75     }
 76 
 77     public final C99HATConfigBuilder camelExceptFirst(String s) {
 78         return identifier(toCamelExceptFirst(s));
 79     }
 80 
 81     public final C99HATConfigBuilder std(String s) {
 82         return identifier("std").colon().colon().identifier(s);
 83     }
 84 
 85     public final C99HATConfigBuilder stdEndl() {
 86         return std("endl");
 87     }
 88 
 89     public final C99HATConfigBuilder stdCout(String s) {
 90         return std("cout").space().leftShift().space().dquote().literal(s).dquote();
 91     }
 92 
 93     public static String create(){
 94         C99HATConfigBuilder cb = new C99HATConfigBuilder(new ScopedCodeBuilderContext(MethodHandles.lookup(),null));
 95         cb.oracleCopyright();
 96         cb.blockComment("""
 97                 You probably should not edit this this file!!!
 98                 It was auto generated""" + " " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " by " + FFIConfigCreator.class.getName()
 99         );
100         cb.pragma("once").nl();
101         cb.includeSys("iostream").nl();
102         final int START_BIT_INDEX = Config.bitList.stream().filter(bit -> bit.size() == 1).findFirst().get().index();
103 
104         cb.structKeyword().space().className().braceNlIndented((_) -> {
105             var i = Mutable.of(START_BIT_INDEX);
106             Config.bitList.stream().filter(bit -> bit.size() == 1).forEach(bit -> {
107                 cb.staticConstIntShiftedOne(bit.name() + "_BIT", 32, i.get());
108                 i.set(i.get() + 1);
109             });
110             cb.constKeyword().space().staticKeyword().space().s08Type().space().asterisk().bitNamesVar().osbrace().csbrace().semicolon().space().lineComment("See below for initialization");
111             cb.constKeyword().space().staticKeyword().space().s08Type().space().asterisk().bitDescriptionsVar().osbrace().csbrace().semicolon().space().lineComment("See below for initialization");
112 
113             cb.s32Type().space().identifier("configBits").semicolon().nl();
114 
115             Config.bitList.stream().filter(bit -> bit.size() == 1).forEach(bit ->
116                     cb.identifier("bool").space().camelExceptFirst(bit.name()).semicolon().nl()
117             );
118 
119             cb.s32Type().space().identifier("platform").semicolon().nl();
120             cb.s32Type().space().identifier("device").semicolon().nl();
121             cb.identifier("bool").space().identifier("alwaysCopy").semicolon().nl();
122             //Constructor
123             cb.explicitKeyword().space().className().paren((_) -> cb.s32Type().space().configBitsVar()).colon().nl().indent((_) -> {
124                 cb.configBitsVar().paren((_) -> cb.configBitsVar()).comma().nl();
125                 Config.bitList.stream().filter(bit -> bit.size() == 1).forEach(bit ->
126                         cb.camelExceptFirst(bit.name()).paren((_) -> cb.paren((_) -> cb.configBitsAndBitName(bit.name())).eq().identifier(bit.name() + "_BIT")).comma().nl()
127                 );
128                 cb.identifier("platform").paren((_) -> cb.configBitsAnd().intHexValue(0xf)).comma().nl();
129                 cb.identifier("alwaysCopy").paren(_ -> cb.pling().camelExceptFirst("MINIMIZE_COPIES")).comma().nl();
130                 cb.identifier("device").paren(_ ->
131                         cb.paren(_ -> cb.configBitsAnd().intHexValue(0xf0)).space().rightShift().space().intValue(4)).braceNlIndented(_ ->
132                         cb.ifKeyword().paren(_ -> cb.identifier("showDeviceInfo")).braceNlIndented(_ -> {
133                             cb.nlSeparated(
134                                     Config.bitList.stream().filter(bit -> bit.size() == 1),
135                                     bit -> cb.stdCout("native " + cb.toCamelExceptFirst(bit.name()) + " ").space().leftShift().space().camelExceptFirst(bit.name()).space().leftShift().space().stdEndl().semicolon()
136                             );
137                             cb.nl().stdCout("native platform ").space().leftShift().space().identifier("platform").space().leftShift().space().stdEndl().semicolon();
138                             cb.nl().stdCout("native device ").space().leftShift().space().identifier("device").space().leftShift().space().stdEndl().semicolon();
139                         })
140                 );
141             }).nl();
142 
143             cb.virtualKeyword().space().tilde().className().ocparen().equals().space().defaultKeyword().semicolon();
144         }).semicolon().nl().nl();
145 
146 
147         cb.hashIfdef("shared_cpp", (_) -> {
148             cb.constKeyword().space().s08Type().space().asterisk().className().colon().colon().bitNamesVar().ocsbrace().equals().brace((_) -> {
149                 cb.nl();
150                 Config.bitList.stream().filter(bit -> bit.size() == 1).forEach(bit ->
151                         cb.dquote().identifier(bit.name() + "_BIT").dquote().comma().nl()
152                 );
153             }).semicolon().nl();
154             cb.constKeyword().space().s08Type().space().asterisk().className().colon().colon().bitDescriptionsVar().ocsbrace().equals().brace((_) -> {
155                 cb.nl();
156                 Config.bitList.stream().filter(bit -> bit.size() == 1).forEach(bit ->
157                         cb.dquote().identifier(bit.description()).dquote().comma().nl()
158                 );
159             }).semicolon().nl();
160         });
161         return cb.toString();
162 
163     }
164 
165     static public void main(){
166         var c = Config.fromSpec("INFO,SHOW_CODE,HEADLESS,SHOW_KERNEL_MODEL,SHOW_COMPUTE_MODEL,PLATFORM:0,DEVICE:0");
167         System.out.println(c);
168         System.out.println(create());
169         System.exit(1);
170     }
171 }